﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UILibrary
{
    /// <summary>
    /// CircularBoard.xaml 的交互逻辑
    /// </summary>
    public partial class ReagentBoard : UserControl
    {

        /// <summary>
        /// 试剂盘数据源
        /// </summary>
        public ObservableCollection<ReagentItemData> DataSource 
        {
            get { return (ObservableCollection<ReagentItemData>)GetValue(DataSourceProperty); }
            set { SetValue(DataSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataSourceProperty =
            DependencyProperty.Register("DataSource", typeof(ObservableCollection<ReagentItemData>), typeof(ReagentBoard), new PropertyMetadata(new ObservableCollection<ReagentItemData>(), (o, e) =>
            {
                var el = o as ReagentBoard;
                if (el != null)
                {
                    el.SelectedIndex = -1;
                    el.RenderItems(el.DataSource.Count,el.DataSource);
                }
            }));

        /// <summary>
        /// 试剂盘Item样式
        /// </summary>
        public List<ReagentItemTypeStyle> TypeStyles
        {
            get { return (List<ReagentItemTypeStyle>)GetValue(TypeStylesProperty); }
            set { SetValue(TypeStylesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TypeStyles.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TypeStylesProperty =
            DependencyProperty.Register("TypeStyles", typeof(List<ReagentItemTypeStyle>), typeof(ReagentBoard), new PropertyMetadata(new List<ReagentItemTypeStyle>()));


        private List<ReagentItem> Items { get; set; } = new();
        public ReagentBoard()
        {
            InitializeComponent();
            this.DataContext = this;

        }
        /// <summary>
        /// selected事件
        /// </summary>
        public static readonly RoutedEvent SelectedChangedEvent =
            EventManager.RegisterRoutedEvent(
            name: "SelectedChanged",
            routingStrategy: RoutingStrategy.Bubble,
            handlerType: typeof(RoutedEventHandler),
            ownerType: typeof(ReagentBoard));

        public event RoutedEventHandler SelectedChanged
        {
            add { base.AddHandler(SelectedChangedEvent, value); }

            remove { base.RemoveHandler(SelectedChangedEvent, value); }
        }

        protected ReagentItem AddItem(double angle,int index,ReagentItemData? data)
        {
            var item = new ReagentItem() { Data = data ?? new ReagentItemData() { Percent = 1 } };
            item.Margin = new Thickness() { Left = reagentRoot.Width / 2, Top = reagentRoot.Height / 2, Bottom = 0, Right = 0 };
            item.Angle = angle;
            item.RadiusInner = RadiusInner;
            item.RadiusOuter = RadiusOuter;
            
            item.Index = index;
            item.Label = (index + 1).ToString();

            item.MouseDown += MouseDownSelect;

            item.TypeStyle = TypeStyles.Find(d => d.Name == data.Type.ToString())!;

            Items.Add(item);

            reagentRoot.Children.Add(item);

            if (!DataSource.Contains(item.Data))
            {
                DataSource.Add(item.Data);
            }
            return item;
        }

        private void MouseDownSelect(object o,EventArgs e)
        {
            var el = o as ReagentItem;
            if (el != null)
            {
                Select(el.Data);

            }
        }

        /// <summary>
        /// 单选
        /// </summary>
        /// <param name="itemData"></param>
        public void Select(ReagentItemData itemData)
        {

            Select(itemData.Index);
        }
        public void Select(int index)
        {
            var item = Items[index];

            var prev = Items.FirstOrDefault(d => d.IsSelected == true);
            if (prev != null)
            {
                prev.IsSelected = false;
            }
            Items[index].IsSelected = true;
            SelectedIndex = index; ;
            SelectedData = item.Data;

            RaiseEvent(new RoutedEventArgs() { RoutedEvent = SelectedChangedEvent, Source = item.Data });
        }
        /// <summary>
        /// 支持多选，未完成
        /// </summary>
        /// <param name="itemDatas"></param>
        public void MutilSelect(IEnumerable<ReagentItemData> itemDatas)
        {
            MutilSignClear();
            foreach (var itemData in itemDatas)
            {
                Items[itemData.Index].IsSigned = true;
            }
        }
        /// <summary>
        /// 多个标记
        /// </summary>
        /// <param name="itemData"></param>
        public void MutilSign(IEnumerable<ReagentItemData> itemDatas)
        {
            MutilSignClear();
            foreach (var itemData in itemDatas)
            {
                Items[itemData.Index].IsSigned = true;
            }
        }
        public void MutilSignClear()
        {
            foreach (var itemData in DataSource)
            {
                Items[itemData.Index].IsSigned = false;
            }
        }
        /// <summary>
        /// 设置item数据,index超出范围时，为新增
        /// </summary>
        /// <param name="index"></param>
        /// <param name="itemData"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public void SetItem(int index,ReagentItemData itemData)
        {
            if(itemData == null)
            {
                throw new ArgumentNullException("itemData不能为null");
            }
            else
            {
                if(itemData.Index<0 || itemData.Index >= DataSource.Count)
                {
                    throw new Exception("index 超出范围");
                }
                else
                {
                    Items[index].Data = itemData;
                }
                
            }
        }
       /// <summary>
       /// 移除
       /// </summary>
       /// <param name="index"></param>
       /// <exception cref="ArgumentNullException"></exception>
        public void RemoveItem(int index)
        {

                if (index < 0 || index <= Items.Count)
                {
                    throw new ArgumentNullException("超出数据组范围");
                }
                Items[index].Data = new ReagentItemData { Index = index };

        }
        /// <summary>
        /// 默认容器数，默认12个，改变其值时，将清空原有数据，根据新的数量重新初始化
        /// </summary>
        public int DefaultItemCount
        {
            get { return (int)GetValue(DefaultItemCountProperty); }
            set
            {

                SetValue(DefaultItemCountProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for ColCount.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DefaultItemCountProperty =
            DependencyProperty.Register("DefaultItemCount", typeof(int), typeof(ReagentBoard), new PropertyMetadata(12, (o, e) =>
            {
                var el = o as ReagentBoard;
                if (el != null)
                {

                    el.RenderItems(el.DefaultItemCount);
                }
            }));

        protected  void RenderItems(int Count,IEnumerable<ReagentItemData> datas = null)
        {
            Items.Clear();
            var arcAngle = (double)(360 / (double)Count);

            if (datas!=null && datas.Count()!=0)
            {
                
                for (int i = 0; i < Count; i++)
                {
                    var itemData = datas.ElementAt(i);
                    AddItem(arcAngle, itemData.Index, datas.ElementAt(i));
                }
            }
            else
            {
                for (int i = 0; i < Count; i++)
                {
                    AddItem(arcAngle, i, null);
                }
            }

        }

        /// <summary>
        /// 选中的序号，当出现多个被选中时,该值为-1;
        /// </summary>
        public int SelectedIndex
        {
            get { return (int)GetValue(SelectedIndexProperty); }
            set { SetValue(SelectedIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedIndexProperty =
            DependencyProperty.Register("SelectedIndex", typeof(int), typeof(ReagentBoard), new PropertyMetadata(-1, (o, e) =>
            {
                var el = o as ReagentBoard;
                if (el != null)
                {
                    try {
                        
                        el.Select(el.SelectedIndex);
                    }
                    catch { }
                }
            }));

        /// <summary>
        /// 选中的数据项，被动，不要赋值
        /// </summary>
        public ReagentItemData SelectedData
        {
            get { return (ReagentItemData)GetValue(SelectedDataProperty); }
            set { SetValue(SelectedDataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedData.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedDataProperty =
            DependencyProperty.Register("SelectedData", typeof(ReagentItemData), typeof(ReagentBoard), new PropertyMetadata(null));




        /// <summary>
        /// 外半径
        /// </summary>
        public double RadiusOuter
        {
            get { return (double)GetValue(RadiusOuterProperty); }
            set
            {
                SetValue(RadiusOuterProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for RadiusOuter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RadiusOuterProperty =
            DependencyProperty.Register("RadiusOuter", typeof(double), typeof(ReagentBoard), new PropertyMetadata(200.0, PropertyChangedCallback));


        /// <summary>
        /// 内半径
        /// </summary>
        public double RadiusInner
        {
            get { return (double)GetValue(RadiusInnerProperty); }
            set
            {
                SetValue(RadiusInnerProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for RadiusInner.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RadiusInnerProperty =
            DependencyProperty.Register("RadiusInner", typeof(double), typeof(ReagentBoard), new PropertyMetadata(0.0, PropertyChangedCallback));


        private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as ReagentBoard;
            if (element != null)
            {
                foreach (var item in element.Items)
                {
                    item.RadiusInner = element.RadiusInner;
                    item.RadiusOuter = element.RadiusOuter;
                }
            }
        }


    }

}
